{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "3c1d7485-de5a-4472-a556-175a9ee89ccc",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[0.03038441 0.99883445 0.67991095]\n",
      " [0.47646241 1.44956558 0.1171028 ]\n",
      " [1.41293548 0.4353713  1.64628995]\n",
      " [1.1466428  1.45635886 0.14168847]\n",
      " [1.17122557 1.06295257 0.7355076 ]\n",
      " [1.41015955 1.184052   0.27915878]\n",
      " [0.57693888 0.12183656 0.9011052 ]\n",
      " [1.78696347 1.20340641 0.57111917]\n",
      " [0.71774212 1.87996283 1.23033401]]\n",
      "[0.63501157 0.12587533 0.67882157 0.56199904]\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[0.  0.2 0.4 0.6 0.8 1.  1.2 1.4 1.6 1.8 2.  2.2 2.4 2.6 2.8 3.  3.2 3.4\n",
      " 3.6 3.8 4.  4.2 4.4 4.6 4.8]\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "返回的数据类型 <class 'list'>\n",
      "数据大小： 3\n",
      "s\n"
     ]
    }
   ],
   "source": [
    "import numpy as np\n",
    "import pandas as pa\n",
    "import matplotlib.pyplot as plt\n",
    "a = np.random.random((9, 3))*2  # 随机生成y\n",
    "print(a)\n",
    "a = np.random.rand(4)\n",
    "print(a)\n",
    "a = np.random.random((9, 3))\n",
    "# 定义一维数组\n",
    "x = np.arange(0, 5, 0.2)\n",
    "y1 = x\n",
    "y2 = x**2\n",
    "y3 = x**3\n",
    "# 使用plot绘制线条\n",
    "linesList = plt.plot(x, y1, 'r*-', x, y2, 'r^-', x, y3, 'r.-')\n",
    "# 用setp方法可以同时设置多个线条的属性\n",
    "plt.setp(linesList, color='r')\n",
    "plt.show()\n",
    "plt.plot((x))\n",
    "print(x)\n",
    "plt.show()\n",
    "print('返回的数据类型', type(linesList))\n",
    "print('数据大小：', len(linesList))\n",
    "print(\"s\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "bafeb052-5c77-43a5-8347-99e82f096894",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 首先创建一个函数和一个Python3.x的新式类\n",
    "class Demo(object):\n",
    "    def __init__(self):\n",
    "        print(\"Demo Class\")\n",
    "# 定义一个函数\n",
    "def function():\n",
    "    print(\"function hahaha\")\n",
    "# 在Python无论是函数，还是类，都是对象，他们可以赋值给一个变量\n",
    "class_value = Demo\n",
    "func_value = function\n",
    "# 并且可以通过变量调用\n",
    "class_value()   # Demo Class\n",
    "func_value()    # function\n",
    "#Step.2\n",
    "# 将函数和类添加到集合中\n",
    "obj_list = []\n",
    "obj_list.append(class_value)\n",
    "obj_list.append(func_value)\n",
    "# 遍历列表\n",
    "for i,v in enumerate(obj_list):\n",
    "    print(i, v)\n",
    "    if i == 1:\n",
    "        v()\n",
    "    # <class '__main__.Demo'>\n",
    "    # <function function at 0x0000020D681B3E18>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "6cf85447",
   "metadata": {},
   "outputs": [],
   "source": [
    "# object是谁实例化的？\n",
    "print(type(object))      # <class 'type'>\n",
    "# object继承自哪个类？\n",
    "print(object.__bases__)  # ()\n",
    "# type是谁实例化的？\n",
    "print(type(type))        # <class 'type'>\n",
    "# type继承自哪个类？\n",
    "print(type.__bases__)    # (<class 'object'>,)\n",
    "# 定义一个变量\n",
    "value = 100\n",
    "# 100由谁实例化？\n",
    "print(type(value))       # <class 'int'>\n",
    "# int由谁实例化？\n",
    "print(type(int))         # <class 'type'>\n",
    "# int继承自哪个类？\n",
    "print(int.__bases__)     # (<class 'object'>,)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "d473506a",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "True\n",
      "False\n",
      "True\n",
      "False\n"
     ]
    }
   ],
   "source": [
    "# instance compare type\n",
    "class A(object):\n",
    "    pass\n",
    "class B(A):\n",
    "    pass\n",
    "b = B()\n",
    "print(isinstance(b, B))\n",
    "print(isinstance(A, A))\n",
    "print(type(b) is B)\n",
    "print(type(b) is A)\n",
    "\n",
    "# True\n",
    "# True\n",
    "# True\n",
    "# False"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "84f5e823",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 此处的类也是模板对象，Python中一切皆对象\n",
    "class A(object):\n",
    "    number = 12#类变量\n",
    "    def __init__(self):\n",
    "        # 实例变量 \n",
    "        self.number_2 = 13\n",
    "# 实例变量只能通过类的实例进行调用\n",
    "print(A.number)      # 12\n",
    "print(A().number)    # 12\n",
    "A.number = [1000,1232,43254,345,35322]\n",
    "print(A().number_2)  # 13\n",
    "print(A().number_2)  # 12\n",
    "print(\"A instance\", A().number, A.number) \n",
    "# 修改模板对象创建的对象的属性，模板对象的属性不会改变\n",
    "a = A()\n",
    "a.number = 18\n",
    "print(a.number)      # 18\n",
    "print(A().number)    # 12\n",
    "print(A.number)      # 12\n",
    "# 修改模板对象的属性，由模板对象创建的对象的属性会改变\n",
    "A.number = 19\n",
    "print(A.number)      # 19\n",
    "print(A().number)    # 19\n",
    "\n",
    "a = A()\n",
    "print(a.number, a.number_2)\n",
    "a.number = 124\n",
    "print(a.number, a.number_2)\n",
    "A.number = 19\n",
    "print(a.number, a.number_2)\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "a89bcfd4",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "None\n"
     ]
    }
   ],
   "source": [
    "class Demo(object):\n",
    "    #class_insatnce\n",
    "    num = []\n",
    "    # 类方法\n",
    "    @classmethod\n",
    "    def class_method(cls, number):\n",
    "        pass\n",
    "    # 静态方法\n",
    "    @staticmethod\n",
    "    def static_method(number):\n",
    "        pass\n",
    "    # 对象方法/实例方法\n",
    "    def object_method(self, number):\n",
    "        pass\n",
    "print(Demo.object_method(1222,23323))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "791eb8ff",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class '__main__.Person'>\n",
      "4\n"
     ]
    }
   ],
   "source": [
    "class Home(object):\n",
    "    # 房间中人数\n",
    "    __number = 0\n",
    "    @classmethod\n",
    "    def add_person_number(cls):\n",
    "        cls.__number += 1\n",
    "    @classmethod\n",
    "    def get_person_number(cls):\n",
    "        return cls.__number\n",
    "    def __new__(self):\n",
    "        Home.add_person_number()\n",
    "        # 重写__new__方法，调用object的__new__\n",
    "        return super().__new__(self)\n",
    "class Person(Home):\n",
    "    def __init__(self):\n",
    "        # 房间人员姓名\n",
    "        self.name = 'name'\n",
    "    # 创建人员对象时调用Home的__new__()方法\n",
    "tom = Person()\n",
    "print(type(tom))   # <class '__main__.Person'>\n",
    "alice = Person()\n",
    "bob = Person()\n",
    "test = Person()\n",
    "print(Home.get_person_number())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "4a7a1da3",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Bruce is 25 weights 180\n"
     ]
    }
   ],
   "source": [
    "class person(object):\n",
    "    tall = 180\n",
    "    hobbies = [12334,123452]\n",
    "    def __init__(self, name, age,weight):\n",
    "        self.name = name\n",
    "        self.age = age\n",
    "        self.weight = weight\n",
    "    def infoma(self):\n",
    "        print('%s is %s weights %s'%(self.name,self.age,self.weight))\n",
    "Bruce = person(\"Bruce\", 25,180)\n",
    "Bruce.infoma()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "5b5e4819",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "person\n",
      "['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'hobbies', 'infoma', 'tall']\n",
      "180 [213, 234, 123432, 123432, 2345, 324, 234]\n"
     ]
    }
   ],
   "source": [
    "class person(object):\n",
    "    tall = 180\n",
    "    hobbies = [213,234,123432,123432,2345,324,234]\n",
    "    def __init__(self, name, age,weight):\n",
    "        self.name = name\n",
    "        self.age = age\n",
    "        self.weight = weight\n",
    "    @classmethod     #类的装饰器\n",
    "    def infoma(cls):   #cls表示类本身，使用类参数cls\n",
    "        print(cls.__name__)\n",
    "        print(dir(cls))\n",
    "        print(cls.tall, cls.hobbies)\n",
    "#cls表示类本身\n",
    "#person.infoma()  直接调用类的装饰器函数，通过cls可以访问类的相关属性\n",
    "Bruce = person(\"Bruce\", 25,180)   #也可以通过两步骤来实现，第一步实例化person，第二步调用装饰器\n",
    "Bruce.infoma() "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b0f80ab1",
   "metadata": {},
   "outputs": [],
   "source": [
    "class person(object):\n",
    "    tall = 180\n",
    "    hobbies = [21324,1,3,53452]\n",
    "    def __init__(self, name, age,weight):\n",
    "        self.name = name\n",
    "        self.age = age\n",
    "        self.weight = weight\n",
    "    @staticmethod    #静态方法装饰器\n",
    "    def infoma():    #没有参数限制，既不要实例参数，也不用类参数\n",
    "        print(person.tall)\n",
    "        print(person.hobbies)\n",
    "person.infoma()     #静态法可以通过类名访问\n",
    "Bruce = person(\"Bruce\", 25,180)   #通过实例访问\n",
    "Bruce.infoma() "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "7d382051",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]\n",
      "child class [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]\n",
      "77 - 2 = 75\n",
      "True\n",
      "True\n",
      "the bases are: (<class '__main__.Parent'>,)\n",
      "None\n",
      "None\n"
     ]
    }
   ],
   "source": [
    "class Parent(object):\n",
    "    numList = []\n",
    "    def numdiff(self, a, b):\n",
    "        return a-b\n",
    "class Child(Parent):\n",
    "    pass\n",
    "c = Child()      \n",
    "Child.numList.extend(range(10))\n",
    "print(Child.numList)\n",
    "print(\"child class\", c.numList)\n",
    "print(\"77 - 2 =\", c.numdiff(77, 2))\n",
    "print(issubclass(Child, Parent))\n",
    "print(issubclass(Child, object))\n",
    "# __bases__ can show all the parent classes\n",
    "#bases属性查看父类\n",
    "print('the bases are:',Child.__bases__)\n",
    "# doc string will not be inherited\n",
    "#doc属性不会被继承\n",
    "print(Parent.__doc__)\n",
    "print(Child.__doc__)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7d1e51ca",
   "metadata": {},
   "outputs": [],
   "source": [
    "# inherit\n",
    "#定义父类：Parent\n",
    "class Parent(object):\n",
    "    def __init__(self, name):\n",
    "        self.name = name\n",
    "        print(\"create an instance of:\", self.__class__.__name__)\n",
    "        print(\"name attribute is:\", self.name)\n",
    "#定义子类Child ，继承父类Parent       \n",
    "class Child(Parent):\n",
    "    def __init__(self,st):\n",
    "        self.names = st\n",
    "        print(\"create an instance of:\", self.__class__.__name__)\n",
    "        print(\"name attribute is init child:\", self.names)\n",
    "        super(Child,self).__init__(\"data from Child\")\n",
    "#子类实例化时，由于子类没有初始化，此时父类的初始化函数就会默认被调用\n",
    "#且必须传入父类的参数name\n",
    "c = Child(\"init Child\")\n",
    "print(c.name, c.names)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ce5bd4f4",
   "metadata": {},
   "outputs": [],
   "source": [
    "# inherit function\n",
    "class Parent(object):\n",
    "    Value = \"Hi, Parent value\"\n",
    "    def fun(self):\n",
    "        print(\"This is from Parent\")\n",
    "\n",
    "class Child(Parent):\n",
    "    Value = \"Hi, Child  value\"\n",
    "    def fun(self):\n",
    "        print(\"This is from Child\")\n",
    "        #Parent.fun(self)\n",
    "        super(Child,self).fun()  #相当于用super的方法与上一调用父类的语句置换\n",
    "\n",
    "c = Child()    \n",
    "c.fun()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b0beec6e",
   "metadata": {},
   "outputs": [],
   "source": [
    "'''\n",
    "\"__“和” _ __\"的使用 更多的是一种规范/约定，并没有真正达到限制的目的：\n",
    "“_”：以单下划线开头的表示的是protected类型的变量，即只能允许其本身与子类进行访问；同时表示弱内部变量标示，如，当使用\"from moduleNmae import *\"时，不会将以一个下划线开头的对象引入。\n",
    "“__”：双下划线的表示的是私有类型的变量。只能是允许这个类本身进行访问了，连子类也不可以，这类属性在运行时属性名会加上单下划线和类名。\n",
    "'''\n",
    "try:\n",
    "    fh = open(\"testfile\", \"w\")\n",
    "    fh.write(\"这是一个测试文件，用于测试异常!!\")\n",
    "except IOError:\n",
    "    print \"Error: 没有找到文件或读取文件失败\"\n",
    "else:\n",
    "    print \"内容写入文件成功\"\n",
    "    fh.close()\n",
    "    \n",
    "    \n",
    "try:\n",
    "    fh = open(\"testfile\", \"w\")\n",
    "    try:\n",
    "        fh.write(\"这是一个测试文件，用于测试异常!!\")\n",
    "    finally:\n",
    "        print \"关闭文件\"\n",
    "        fh.close()\n",
    "except IOError:\n",
    "    print \"Error: 没有找到文件或读取文件失败\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "91425ddc",
   "metadata": {},
   "outputs": [],
   "source": [
    "# map可以用于对可遍历结构的每个元素执行同样的操作，批量操作：\n",
    "map(lambda x: x**2, [1, 2, 3, 4])                 # [1, 4, 9, 16]\n",
    "map(lambda x, y: x + y, [1, 2, 3], [5, 6, 7])     # [6, 8, 10]\n",
    "# 在Python3种输出上述结果\n",
    "result1=list(map(lambda x: x**2, [1, 2, 3, 4]) )                # [1, 4, 9, 16]\n",
    "print(result1)\n",
    "result2 = (map(lambda x, y: x + y, [1, 2, 3], [5, 6, 7]))     # [6, 8, 10]\n",
    "print(result2)\n",
    "# reduce则是对可遍历结构的元素按顺序进行两个输入参数的操作\n",
    "# 并且每次的结果保存作为下次操作的第一个输入参数，还没有遍历的元素作为第二个输入参数\n",
    "# 这样的结果就是把一串可遍历的值，减少（reduce）成一个对象\n",
    "from functools import reduce\n",
    "res=reduce(lambda x, y: x + y, [1, 2, 3, 4])    # ((1+2)+3)+4=10\n",
    "print(res)\n",
    "# filter顾名思义，根据条件对可遍历结构进行筛选\n",
    "filter(lambda x: x % 2, [1, 2, 3, 4, 5])    # 筛选奇数，[1, 3, 5]\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "326cba74",
   "metadata": {},
   "outputs": [],
   "source": [
    "# thread\n",
    "import time, threading\n",
    "# 新线程执行的代码:\n",
    "def loop():\n",
    "    print('thread %s is running...' % threading.current_thread().name)\n",
    "    n = 0\n",
    "    while n < 5:\n",
    "        n = n + 1\n",
    "        print('thread %s >>> %s' % (threading.current_thread().name, n))\n",
    "        time.sleep(1)\n",
    "    print('thread %s ended.' % threading.current_thread().name)\n",
    "\n",
    "print('thread %s is running...' % threading.current_thread().name)\n",
    "t = threading.Thread(target=loop, name='LoopThread')\n",
    "t.start()\n",
    "t.join()\n",
    "print('thread %s ended.' % threading.current_thread().name)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a2ba0a40",
   "metadata": {},
   "outputs": [],
   "source": [
    "from urllib import request\n",
    "with request.urlopen('https://www.baidu.com') as f:\n",
    "    data = f.read()\n",
    "    print('Status:', f.status, f.reason)\n",
    "    for k, v in f.getheaders():\n",
    "        print('%s: %s' % (k, v))\n",
    "    print('Data:', data.decode('utf-8'))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "33aa3867",
   "metadata": {},
   "outputs": [],
   "source": [
    "import psutil\n",
    "psutil.cpu_count()  # CPU逻辑数量\n",
    "psutil.cpu_count(logical=False)  # CPU物理核心\n",
    "#psutil.test()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "649a2309",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 导入SQLite驱动:\n",
    "import sqlite3\n",
    "# 连接到SQLite数据库\n",
    "# 数据库文件是test.db\n",
    "# 如果文件不存在，会自动在当前目录创建:\n",
    "conn = sqlite3.connect('test.db')\n",
    "# 创建一个Cursor:\n",
    "cursor = conn.cursor()\n",
    "# 执行一条SQL语句，创建user表:\n",
    "cursor.execute('create table user (id varchar(20) primary key, name varchar(20))')\n",
    "#<sqlite3.Cursor object at 0x10f8aa260>\n",
    "# 继续执行一条SQL语句，插入一条记录:\n",
    "cursor.execute('insert into user (id, name) values (\\'1\\', \\'Michael\\')')\n",
    "#<sqlite3.Cursor object at 0x10f8aa260>\n",
    "# 通过rowcount获得插入的行数:\n",
    "print(\"insert line : \",cursor.rowcount)\n",
    "# 关闭Cursor:\n",
    "cursor.close()\n",
    "# 提交事务:\n",
    "conn.commit()\n",
    "# 关闭Connection:\n",
    "conn.close()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c1f851b6",
   "metadata": {},
   "outputs": [],
   "source": [
    "conn = sqlite3.connect('test.db')\n",
    "cursor = conn.cursor()\n",
    "# 执行查询语句:\n",
    "cursor.execute('select * from user where id=?', ('1',))\n",
    "#<sqlite3.Cursor object at 0x10f8aa340>\n",
    "# 获得查询结果集:\n",
    "values = cursor.fetchall()\n",
    "print(\"get result : \", values, type(values))\n",
    "cursor.close()\n",
    "conn.close()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7a8a767c",
   "metadata": {},
   "outputs": [],
   "source": [
    "from __future__ import print_function\n",
    "import torch\n",
    "import numpy\n",
    "x = torch.Tensor(5, 3)\n",
    "print(x, type(x))\n",
    "y = numpy.random.ranf((5, 3))\n",
    "print(y, type(y), numpy.shape(y))\n",
    "x = torch.rand(5, 3)\n",
    "print(x, type(x), x.size())\n",
    "a = torch.rand(5, 3)\n",
    "b = torch.Tensor(5, 3)\n",
    "print(a, type(a), b, type(b))\n",
    "c = torch.add(a, b)\n",
    "print(a, type(a), b, type(b),c, type(c))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "1a38e16a",
   "metadata": {},
   "outputs": [],
   "source": [
    "import torch\n",
    "x = torch.rand(2, 2)\n",
    "y = torch.rand(2, 2)\n",
    "print(x, \"x\")\n",
    "print(y, \"y\")\n",
    "print(x + y)\n",
    "print(torch.add(x, y))\n",
    "x += y\n",
    "print(x)\n",
    "print(x[1, :], \"qq\")\n",
    "x = torch.rand(4, 4)\n",
    "print(x, x.size(), x.dtype)\n",
    "y = x.view(2, 8)\n",
    "print(y)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "912c233d",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([[0, 0, 0],\n",
      "        [0, 0, 0],\n",
      "        [0, 0, 0],\n",
      "        [0, 0, 0],\n",
      "        [0, 0, 0]])\n",
      "torch.Size([5, 3])\n",
      "torch.int64\n",
      "[3124234, 123421] tensor([3124234.,  123421.]) <class 'list'> <class 'torch.Tensor'>\n",
      "tensor([0.5253, 0.2487])\n",
      "tensor([0.2487])\n"
     ]
    }
   ],
   "source": [
    "import torch\n",
    "x = torch.zeros(5, 3, dtype=torch.long)\n",
    "print(x)\n",
    "print(x.size())\n",
    "print(x.dtype)\n",
    "l = [3124234,123421]\n",
    "x = torch.Tensor(l)\n",
    "print(l, x, type(l), type(x))\n",
    "x = torch.rand_like(x, dtype=torch.float)\n",
    "print(x)\n",
    "print(x[1:])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "f0ddb08a",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([1., 1., 1., 1., 1.]) <class 'torch.Tensor'>\n",
      "[1. 1. 1. 1. 1.] <class 'numpy.ndarray'>\n",
      "[1. 1. 1. 1. 1.] <class 'numpy.ndarray'>\n",
      "[2. 2. 2. 2. 2.] <class 'numpy.ndarray'>\n",
      "tensor([2., 2., 2., 2., 2.], dtype=torch.float64) <class 'torch.Tensor'>\n",
      "no surrport cuda\n"
     ]
    }
   ],
   "source": [
    "import numpy \n",
    "import torch\n",
    "a = torch.ones(5)\n",
    "print(a, type(a))\n",
    "b = a.numpy() # torch to numpy (tensor -> ndarray)\n",
    "print(b, type(b))\n",
    "a = numpy.ones(5)\n",
    "print(a, type(a))\n",
    "b = torch.from_numpy(a)\n",
    "numpy.add(a, 1, out=a)\n",
    "print(a ,type(a))\n",
    "print(b, type(b))\n",
    "if torch.cuda.is_available():\n",
    "    device = torch.device(\"cuda\")          # a CUDA device object\n",
    "    y = torch.ones_like(x, device=device)  # 直接在GPU上创建tensor\n",
    "    x = x.to(device)                       # 或者使用`.to(\"cuda\")`方法\n",
    "    z = x + y\n",
    "    print(z)\n",
    "    print(z.to(\"cpu\", torch.double))       # `.to`也能在移动时改变dtyp\n",
    "else:\n",
    "    print(\"no surrport cuda\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "8f042e99",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "输出的结果：\n",
      "tensor([1., 2., 3.])\n",
      "tensor([1, 2, 3], dtype=torch.int32)\n",
      "tensor([1, 2, 3], dtype=torch.int32)\n",
      "tensor([1, 2, 3], dtype=torch.int32)\n",
      "输出的类型：\n",
      "torch.float32\n",
      "torch.int32\n",
      "torch.int32\n",
      "torch.int32\n",
      "torch.float32\n"
     ]
    }
   ],
   "source": [
    "import torch\n",
    "import numpy as np\n",
    "data = np.array([1, 2, 3])\n",
    "\n",
    "Tensor = torch.Tensor(data)\n",
    "tensor = torch.tensor(data)\n",
    "from_numpy = torch.from_numpy(data)\n",
    "as_tensor = torch.as_tensor(data)\n",
    "print('输出的结果：')\n",
    "print(Tensor)\n",
    "print(tensor)\n",
    "print(from_numpy)\n",
    "print(as_tensor)\n",
    "\n",
    "print('输出的类型：')\n",
    "print(Tensor.dtype)\n",
    "print(tensor.dtype)\n",
    "print(from_numpy.dtype)\n",
    "print(as_tensor.dtype)\n",
    "print(torch.get_default_dtype())\n",
    "# from_numpy as_tensor 浅拷贝， 推荐使用 as_tensor，可以接受 python 原生 list\n",
    "# tensor Tensor 深拷贝"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "9e595f0f",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "id": "26321eeb",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[ 12 334]\n",
      " [223  33]] <class 'numpy.ndarray'> int32\n",
      "tensor([[ 12., 334.],\n",
      "        [223.,  33.]], dtype=torch.float64, requires_grad=True) <class 'torch.Tensor'> torch.float64\n",
      "tensor([[ 44., 366.],\n",
      "        [255.,  65.]], dtype=torch.float64, grad_fn=<AddBackward0>) <class 'torch.Tensor'> torch.float64\n",
      "tensor([[ 88.0432, 732.4445],\n",
      "        [510.6843, 130.1294]], dtype=torch.float64, grad_fn=<AddBackward0>) <class 'torch.Tensor'> torch.float64\n",
      "<AddBackward0 object at 0x000002A33CD38A90>\n"
     ]
    }
   ],
   "source": [
    "import torch\n",
    "import numpy as np\n",
    "a = numpy.array([[12,334],[223,33]])\n",
    "print(a, type(a), a.dtype)\n",
    "b = torch.tensor(a, dtype=torch.float64, requires_grad=True)\n",
    "print(b, type(b), b.dtype)\n",
    "b = b + 32\n",
    "print(b, type(b), b.dtype)\n",
    "b = b * 2\n",
    "b = b + torch.rand(2,2)\n",
    "print(b, type(b), b.dtype) #numpy 默认 int32, tensor float32\n",
    "print(b.grad_fn)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "id": "ddc87fc0",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "False\n",
      "True\n",
      "<SumBackward0 object at 0x000002A33BB59160>\n",
      "None\n",
      "tensor([-0.1271,  1.0101, -0.2528], requires_grad=True) x\n",
      "tensor([-0.2542,  2.0203, -0.5057], grad_fn=<MulBackward0>) y\n",
      "tensor([-130.1741, 1034.3812, -258.9066], grad_fn=<MulBackward0>)\n"
     ]
    }
   ],
   "source": [
    "import torch\n",
    "a = torch.randn(2, 2)\n",
    "a = ((a * 3) / (a - 1))\n",
    "print(a.requires_grad)\n",
    "a.requires_grad_(True)\n",
    "print(a.requires_grad)\n",
    "b = (a * a).sum()\n",
    "print(b.grad_fn)\n",
    "print(b.backward())\n",
    "\n",
    "x = torch.randn(3, requires_grad=True)\n",
    "print(x, \"x\")\n",
    "y = x * 2\n",
    "print(y, \"y\")\n",
    "while y.data.norm() < 1000:\n",
    "    y = y * 2\n",
    "\n",
    "print(y)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "id": "4879aa45",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "in, out tensor([[ 0.0023, -0.0492,  0.6475],\n",
      "        [ 1.5920,  0.8618,  0.4290],\n",
      "        [-0.4689, -1.2290, -0.1098],\n",
      "        [-0.6031,  1.0772,  0.2740]])\n",
      "out tensor([ 1.4511,  0.7946, -0.3832])\n",
      "tensor([[-0.9880, -0.5954,  1.1387, -1.7593],\n",
      "        [-0.6070, -0.1915, -0.3441,  0.2134]])\n",
      "tensor([[5.8682, 2.7789, 2.2047],\n",
      "        [2.2672, 0.3739, 0.8371]], grad_fn=<AddBackward0>)\n",
      "w Parameter containing:\n",
      "tensor([[-1.5243, -1.3288, -0.4123],\n",
      "        [ 1.1014,  0.7649, -2.3730],\n",
      "        [ 1.5260,  0.7510, -0.0406],\n",
      "        [-0.6094, -0.5546, -0.1583]], requires_grad=True)\n",
      "b Parameter containing:\n",
      "tensor([2.2080, 0.0905, 0.1523], requires_grad=True)\n"
     ]
    }
   ],
   "source": [
    "import torch as t\n",
    "from torch import nn\n",
    "class Linear(nn.Module): # 继承nn.Module\n",
    "    def __init__(self, in_features, out_features):\n",
    "        super(Linear, self).__init__() # 等价于nn.Module.__init__(self)\n",
    "        self.w = nn.Parameter(t.randn(in_features, out_features))\n",
    "        self.b = nn.Parameter(t.randn(out_features))\n",
    "    \n",
    "    def forward(self, x):\n",
    "        x = x.mm(self.w) # x.@(self.w)\n",
    "        return x + self.b.expand_as(x)\n",
    "layer = Linear(4, 3)\n",
    "print(\"in, out\", t.randn(4,3))\n",
    "print(\"out\", t.randn(3))\n",
    "input = t.randn(2,4)\n",
    "print(input)\n",
    "output = layer(input)\n",
    "print(output)\n",
    "\n",
    "for name, parameter in layer.named_parameters():\n",
    "    print(name, parameter) #"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "b98bd6fa",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0 32506.076767304214\n",
      "1 32287.562098715585\n",
      "2 32071.000172256063\n",
      "3 31856.36941025196\n",
      "4 31643.648524599565\n",
      "5 31432.816512084588\n",
      "6 31223.852649791188\n",
      "7 31016.736490598858\n",
      "8 30811.447858765005\n",
      "9 30607.966845591473\n",
      "10 30406.273805173103\n",
      "11 30206.34935022653\n",
      "12 30008.174347997407\n",
      "13 29811.920405968955\n",
      "14 29617.50676603211\n",
      "1626761165.5033305\n"
     ]
    }
   ],
   "source": [
    "# -*- coding: utf-8 -*-\n",
    "import numpy as np\n",
    "import time\n",
    "# N is batch size; D_in is input dimension;\n",
    "# H is hidden dimension; D_out is output dimension.\n",
    "N, D_in, H, D_out = 4, 10, 100, 10\n",
    "\n",
    "# Create random input and output data\n",
    "x = np.random.randn(N, D_in)\n",
    "y = np.random.randn(N, D_out)\n",
    "\n",
    "# Randomly initialize weights\n",
    "w1 = np.random.randn(D_in, H)\n",
    "w2 = np.random.randn(H, D_out)\n",
    "\n",
    "learning_rate = 1e-6\n",
    "t = time.time()\n",
    "for t in range(15):\n",
    "    # Forward pass: compute predicted y\n",
    "    h = x.dot(w1)\n",
    "    h_relu = np.maximum(h, 0)\n",
    "    y_pred = h_relu.dot(w2)\n",
    "\n",
    "    # Compute and print loss\n",
    "    loss = np.square(y_pred - y).sum()\n",
    "    print(t, loss)\n",
    "\n",
    "    # Backprop to compute gradients of w1 and w2 with respect to loss\n",
    "    grad_y_pred = 2.0 * (y_pred - y)\n",
    "    grad_w2 = h_relu.T.dot(grad_y_pred)\n",
    "    grad_h_relu = grad_y_pred.dot(w2.T)\n",
    "    grad_h = grad_h_relu.copy()\n",
    "    grad_h[h < 0] = 0\n",
    "    grad_w1 = x.T.dot(grad_h)\n",
    "\n",
    "    # Update weights\n",
    "    w1 -= learning_rate * grad_w1\n",
    "    w2 -= learning_rate * grad_w2\n",
    "print(time.time() -t)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "4a4cabe5",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1626761255.493857\n"
     ]
    }
   ],
   "source": [
    "# -*- coding: utf-8 -*-\n",
    "\n",
    "import torch\n",
    "\n",
    "dtype = torch.float\n",
    "device = torch.device(\"cpu\")\n",
    "# device = torch.device(\"cuda:0\") # Uncomment this to run on GPU\n",
    "\n",
    "# N is batch size; D_in is input dimension;\n",
    "# H is hidden dimension; D_out is output dimension.\n",
    "N, D_in, H, D_out = 4, 10, 100, 10\n",
    "\n",
    "# Create random input and output data\n",
    "x = torch.randn(N, D_in, device=device, dtype=dtype)\n",
    "y = torch.randn(N, D_out, device=device, dtype=dtype)\n",
    "\n",
    "# Randomly initialize weights\n",
    "w1 = torch.randn(D_in, H, device=device, dtype=dtype)\n",
    "w2 = torch.randn(H, D_out, device=device, dtype=dtype)\n",
    "\n",
    "learning_rate = 1e-6\n",
    "t = time.time()\n",
    "for t in range(15):\n",
    "    # Forward pass: compute predicted y\n",
    "    h = x.mm(w1)\n",
    "    h_relu = h.clamp(min=0)\n",
    "    y_pred = h_relu.mm(w2)\n",
    "\n",
    "    # Compute and print loss\n",
    "    loss = (y_pred - y).pow(2).sum().item()\n",
    "    if t % 100 == 99:\n",
    "        print(t, loss)\n",
    "\n",
    "    # Backprop to compute gradients of w1 and w2 with respect to loss\n",
    "    grad_y_pred = 2.0 * (y_pred - y)\n",
    "    grad_w2 = h_relu.t().mm(grad_y_pred)\n",
    "    grad_h_relu = grad_y_pred.mm(w2.t())\n",
    "    grad_h = grad_h_relu.clone()\n",
    "    grad_h[h < 0] = 0\n",
    "    grad_w1 = x.t().mm(grad_h)\n",
    "\n",
    "    # Update weights using gradient descent\n",
    "    w1 -= learning_rate * grad_w1\n",
    "    w2 -= learning_rate * grad_w2\n",
    "print(time.time() - t)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "7fb7dc5a",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Dataset FashionMNIST\n",
      "    Number of datapoints: 60000\n",
      "    Root location: data\n",
      "    Split: Train\n",
      "    StandardTransform\n",
      "Transform: ToTensor() <class 'torchvision.datasets.mnist.FashionMNIST'> 2926\n",
      "Dataset FashionMNIST\n",
      "    Number of datapoints: 60000\n",
      "    Root location: data\n",
      "    Split: Train\n",
      "    StandardTransform\n",
      "Transform: ToTensor() <class 'torchvision.datasets.mnist.FashionMNIST'> 50176\n",
      "Dataset FashionMNIST\n",
      "    Number of datapoints: 60000\n",
      "    Root location: data\n",
      "    Split: Train\n",
      "    StandardTransform\n",
      "Transform: ToTensor() <class 'torchvision.datasets.mnist.FashionMNIST'> 32637\n",
      "Dataset FashionMNIST\n",
      "    Number of datapoints: 60000\n",
      "    Root location: data\n",
      "    Split: Train\n",
      "    StandardTransform\n",
      "Transform: ToTensor() <class 'torchvision.datasets.mnist.FashionMNIST'> 32418\n",
      "Dataset FashionMNIST\n",
      "    Number of datapoints: 60000\n",
      "    Root location: data\n",
      "    Split: Train\n",
      "    StandardTransform\n",
      "Transform: ToTensor() <class 'torchvision.datasets.mnist.FashionMNIST'> 32175\n",
      "Dataset FashionMNIST\n",
      "    Number of datapoints: 60000\n",
      "    Root location: data\n",
      "    Split: Train\n",
      "    StandardTransform\n",
      "Transform: ToTensor() <class 'torchvision.datasets.mnist.FashionMNIST'> 54312\n",
      "Dataset FashionMNIST\n",
      "    Number of datapoints: 60000\n",
      "    Root location: data\n",
      "    Split: Train\n",
      "    StandardTransform\n",
      "Transform: ToTensor() <class 'torchvision.datasets.mnist.FashionMNIST'> 48371\n",
      "Dataset FashionMNIST\n",
      "    Number of datapoints: 60000\n",
      "    Root location: data\n",
      "    Split: Train\n",
      "    StandardTransform\n",
      "Transform: ToTensor() <class 'torchvision.datasets.mnist.FashionMNIST'> 43974\n",
      "Dataset FashionMNIST\n",
      "    Number of datapoints: 60000\n",
      "    Root location: data\n",
      "    Split: Train\n",
      "    StandardTransform\n",
      "Transform: ToTensor() <class 'torchvision.datasets.mnist.FashionMNIST'> 22462\n"
     ]
    },
    {
     "data": {
      "image/png": "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VSazV4lBTpo0Kavz8eoTTjghazNixIhC+ZZbbsna7LvvvoXy61//+qxN//75vvA33HBDoewXtJCkJ554olCOYuWPPfZYoXz33XdnbWbPnp3VVYn7R4sQdDSeJAEAKMEgCQBACQZJAABKMEgCAFDC2pug2Qq7MWD76am7gEQJNzfddFOhvHTp0qyNTzSI/rZ8osHo0aOzNlEyzTHHHFMo+0QeSZo3b16hHO1UsttuuxXKPvFDkm699das7q1vfWtWt710t11ATj755EL5pJNOytoMHjw4q/Of1aZNm7I2fjeYIUOGZG3+8Ic/FMpHH3101mb33XfP6n73u98VytEOI2vXri2Uo8Uq+vTpUyhHi2VECxz46/7hD3+Yteko7AICAEATGCQBACjBIAkAQAlikijVE2KSI0eOzOoefPDBrM7v5r5+/fqsjY/HRBOdN2/eXChPmTIla/PZz342q3vb295WKE+YMCFr4xeyrjLReuedd87qoont119/faH893//9w2P3axWikl6xx13XFZ37rnnFsq+D0jxggM+dhfFmH2/7NevX9bGxztXrVqVtVmxYkVW5xc4j+KN/lg+jirlcdro94jqfLz1m9/8ZtYm+lttBjFJAACawCAJAEAJBkkAAEowSAIAUIJdQNCjRUkyPmFAyhMbogSFXXfdteH5fBJDtCN8tPuBP180+dsnf0TJED6Zxyd+SNLChQuzug996EOF8vZM3GllZ511VlbnJ9xHiTtRn/OifuFf588l5YsQDBgwIGsTJfysWbOmUI6uu2/fvoVy1J922aU4zETJotF1+9/X77IjdVziTnt4kgQAoASDJAAAJRgkAQAoQUxyO5g4cWKhPHfu3KaOE8WUquzWjere+MY3ZnXRAszRZ9FIFHvxddHnGZ3Lvy6afO6PFS0m4OuixQQiPia79957Z21mzpxZ6VjdiY/l9e/fP2uzcuXKhsdZt25dVlclTulFcXF/nGih9CjeWCUOvnHjxobXFP09NTqXlPfnaAGNzsCTJAAAJRgkAQAowSAJAEAJBkkAAEq0XOJOlZ0N2tvZpOw40Wv8JFgpT5iIdhn3O8vffvvtWZuLL764UH7mmWeyNs0m6fjf7cgjj8zaPPDAA00du7vZa6+9sroFCxZkdVFiQSPRrglV+m/VXRI6QpToESUF+XZveMMbsjY9MXFn6tSphXJ0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\n",
      "text/plain": [
       "<Figure size 576x576 with 9 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "import torch\n",
    "import matplotlib.pyplot as plt\n",
    "from torch.utils.data import Dataset\n",
    "from torchvision import datasets\n",
    "from torchvision.transforms import ToTensor\n",
    "'''\n",
    "training_data = datasets.FashionMNIST(\n",
    "    root=\"data\",\n",
    "    train=True,\n",
    "    download=True,\n",
    "    transform=ToTensor()\n",
    ")\n",
    "\n",
    "test_data = datasets.FashionMNIST(\n",
    "    root=\"data\",\n",
    "    train=False,\n",
    "    download=True,\n",
    "    transform=ToTensor()\n",
    ")\n",
    "'''\n",
    "labels_map = {\n",
    "    0: \"T-Shirt\",\n",
    "    1: \"Trouser\",\n",
    "    2: \"Pullover\",\n",
    "    3: \"Dress\",\n",
    "    4: \"Coat\",\n",
    "    5: \"Sandal\",\n",
    "    6: \"Shirt\",\n",
    "    7: \"Sneaker\",\n",
    "    8: \"Bag\",\n",
    "    9: \"Ankle Boot\",\n",
    "}\n",
    "figure = plt.figure(figsize=(8, 8))\n",
    "cols, rows = 3, 3\n",
    "for i in range(1, cols * rows + 1):\n",
    "    sample_idx = torch.randint(len(training_data), size=(1,)).item()\n",
    "    print(training_data, type(training_data), sample_idx)\n",
    "    img, label = training_data[sample_idx]\n",
    "    figure.add_subplot(rows, cols, i)\n",
    "    plt.title(labels_map[label])\n",
    "    plt.axis(\"off\")\n",
    "    plt.imshow(img.squeeze(), cmap=\"gray\")\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "5b04c772",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.8"
  },
  "widgets": {
   "application/vnd.jupyter.widget-state+json": {
    "state": {},
    "version_major": 2,
    "version_minor": 0
   }
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
